import * as https from "https";
import * as retry from "async-retry";
import { fetch, toPassportConfig } from "passport-saml-metadata";
export class Config {
    public static nodered_id: string = Config.getEnv("nodered_id", "1");

    public static consumer_key: string = Config.getEnv("consumer_key", "");
    public static consumer_secret: string = Config.getEnv("consumer_secret", "");

    public static saml_federation_metadata: string = Config.getEnv("saml_federation_metadata", "");
    public static saml_issuer: string = Config.getEnv("saml_issuer", "");
    public static saml_entrypoint: string = Config.getEnv("saml_entrypoint", "");
    public static saml_crt: string = Config.getEnv("saml_crt", "");

    public static tls_crt: string = Config.getEnv("tls_crt", "");
    public static tls_key: string = Config.getEnv("tls_key", "");
    public static tls_ca: string = Config.getEnv("tls_ca", "");
    public static tls_passphrase: string = Config.getEnv("tls_passphrase", "");
    public static port: number = parseInt(Config.getEnv("port", "1880"));
    public static domain: string = Config.getEnv("domain", "localhost");
    public static api_ws_url: string = Config.getEnv("api_ws_url", "ws://localhost:3000");
    public static amqp_url: string = Config.getEnv("amqp_url", "amqp://localhost");

    public static api_credential_cache_seconds: number = parseInt(Config.getEnv("api_credential_cache_seconds", "300"));
    public static api_allow_anonymous: boolean = Config.parseBoolean(Config.getEnv("api_allow_anonymous", "false"));

    public static aes_secret: string = Config.getEnv("aes_secret", "");

    public static baseurl(): string {
        if (Config.tls_crt != '' && Config.tls_key != '') {
            return "https://" + Config.domain + ":" + Config.port + "/";
        }
        return "http://" + Config.domain + ":" + Config.port + "/";
    }

    public static getEnv(name: string, defaultvalue: string): string {
        var value: any = process.env[name];
        if (!value || value === "") { value = defaultvalue; }
        return value;
    }
    public static parseBoolean(s:any):boolean {
        var val:string = "false";
        if (typeof s === "number") {
            val = s.toString();
        } else if (typeof s === "string") {
            val = s.toLowerCase().trim();
        } else if (typeof s === "boolean") {
            val = s.toString();
        } else {
            throw new Error("Unknown type!");
        }
        switch(val) {
            case "true": case "yes": case "1": return true;
            case "false": case "no": case "0": case null: return false;
            default: return Boolean(s);
        }
    }

    public static async parse_federation_metadata(url: string): Promise<any> {


        try {
            if (Config.tls_ca !== "") {
                var tls_ca: string = Buffer.from(Config.tls_ca, 'base64').toString('ascii')
                var rootCas = require('ssl-root-cas/latest').create();
                rootCas.push(tls_ca);
                // rootCas.addFile( tls_ca );
                https.globalAgent.options.ca = rootCas;
                require('https').globalAgent.options.ca = rootCas;
            }
        } catch (error) {
            console.log(error);
        }

        // if anything throws, we retry
        var metadata: any = await retry(async bail => {
            process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
            var reader: any = await fetch({ url });
            process.env.NODE_TLS_REJECT_UNAUTHORIZED = "1";
            if (reader === null || reader === undefined) { bail(new Error("Failed getting result")); return; }
            var config: any = toPassportConfig(reader);
            // we need this, for Office 365 :-/
            if (reader.signingCerts && reader.signingCerts.length > 1) {
                config.cert = reader.signingCerts;
            }
            return config;
        }, {
                retries: 50,
                onRetry: function (error: Error, count: number): void {
                    console.log("retry " + count + " error " + error.message + " getting " + url);
                }
            });
        return metadata;
    }
}
